package com.suxin.logger;

import com.suxin.logger.filter.Filter;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author Tang
 * @classname LogRecord
 * @description [  ]
 * @date 2022/4/26 22:12
 */
public class LogRecord {

    private AtomicLong globalSequenceNumber = new AtomicLong(0);
    private Long logSequence;

    private String loggerName;
    private Level level;
    private String msg;
    private int threadId;
    private Long millis;

    private Object[] parameters;

    private static final int MIN_SEQUENCE_THREAD_ID = Integer.MAX_VALUE / 2;
    private static final AtomicInteger nextThreadId = new AtomicInteger(MIN_SEQUENCE_THREAD_ID);
    private static final ThreadLocal<Integer> threadIds = new ThreadLocal<>();

    private int defaultThreadId() {
        long tid = Thread.currentThread().getId();
        if (tid < MIN_SEQUENCE_THREAD_ID) {
            return (int) tid;
        }else {
            Integer id = threadIds.get();
            if (id == null) {
                id = nextThreadId.getAndIncrement();
                threadIds.set(id);
            }
            return id;
        }
    }

    public LogRecord(Level level, String msg) {
        this.level = level;
        this.msg = msg;
        this.logSequence = globalSequenceNumber.getAndIncrement();
        this.threadId = defaultThreadId();
        this.millis = System.currentTimeMillis();
    }

    public Object[] getParameters() {
        return parameters;
    }

    public void setParameters(Object[] parameters) {
        this.parameters = parameters;
    }

    public String getLoggerName() {
        return loggerName;
    }

    public void setLoggerName(String loggerName) {
        this.loggerName = loggerName;
    }

    public Level getLevel() {
        return level;
    }

    public void setLevel(Level level) {
        this.level = level;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Long getMillis() {
        return millis;
    }

    public void setMillis(Long millis) {
        this.millis = millis;
    }
}